import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'package:tiktokadult/alert_business/video/vip_dailog.dart';
import 'package:tiktokadult/hj_page/short_video/view/short_video_menu.dart';
import 'package:tiktokadult/tools_base/debug_log.dart';
import 'package:video_player/video_player.dart';

import '../../../hj_utils/widget_util.dart';

class ShortProgressWidget extends StatefulWidget {
  final EdgeInsets? padding;
  final VideoPlayerController? controller;
  final Function(bool)? gestureCallback; // true 开始， false 结束
  final Function(Duration?)? skipCallback;
  final bool isShortStyle;

  const ShortProgressWidget({
    Key? key,
    this.padding,
    this.controller,
    this.gestureCallback,
    this.skipCallback,
    this.isShortStyle = true,
  }) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return ShortProgressWidgetState();
  }
}

class ShortProgressWidgetState extends State<ShortProgressWidget> {
  VideoPlayerController? _controller;

  VideoPlayerController? get controller {
    return _controller;
  }

  GlobalKey currentKey = GlobalKey();
  Duration? seekPos;

  double get playDuration {
    if (controller == null) return 0;
    if (controller!.value.duration.inMilliseconds <= 0) {
      return 0;
    }
    Duration? showDuration = seekPos ?? controller!.value.position;
    double duration = showDuration.inMilliseconds / controller!.value.duration.inMilliseconds;
    if (duration < 0) return 0;
    return duration;
  }

  double progressWidth = 0;

  double get circleWidth => widget.isShortStyle ? 0 : 12;

  double get _offset {
    double offset = progressWidth * playDuration;
    if (offset < 0) {
      offset = 0;
    }
    if (offset > progressWidth) {
      offset = progressWidth;
    }
    return offset;
  }

  double get progressValue {
    int duration = controller?.value.duration.inMilliseconds ?? 1;
    return playDuration / duration;
  }

  String timerFormatMMSS(int seconds) {
    int hour = seconds ~/ 3600;
    int minute = seconds ~/ 60;
    int second = seconds % 60;
    if (hour > 0) {
      minute = (seconds % 3600) ~/ 60;
      return "${_formatTime(hour)}:${_formatTime(minute)}:${_formatTime(second)}";
    } else {
      return "${_formatTime(minute)}:${_formatTime(second)}";
    }
  }

  String _formatTime(int timeNum) {
    return timeNum.toString().padLeft(2, "0");
  }

  bool get isVisible {
    if (!_isShowMenu) {
      return false;
    }
    return true;
  }

  bool _isShowMenu = true;

  void _menuShowListener(bool isShow) {
    _isShowMenu = isShow;
    setState(() {});
  }

  @override
  void initState() {
    super.initState();
    ShortVideoMenu.addListen(_menuShowListener);
    _controller = widget.controller;
    if (_controller != null) {
      _controller?.addListener(_listenCallBack);
    }
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (mounted) {
        progressWidth = (currentKey.currentContext?.size?.width ?? 0) - circleWidth;
        if (progressWidth < 0) progressWidth = 0;
      }
      setState(() {});
    });
  }

  void seekToRelativePosition(Offset globalPosition) {
    if (controller == null) return;
    double width = WidgetUtil.findGlobalRect(currentKey)!.width;
    double xOffSet = WidgetUtil.globalOffsetToLocal(currentKey, globalPosition)!.dx;
    double relative = xOffSet / width;
    if (relative < 0) {
      relative = 0;
    }
    if (relative.isNaN != true) {
      seekPos = controller!.value.duration * relative;
    }
    widget.skipCallback?.call(seekPos);
    setState(() {});
  }

  void configVideoController(VideoPlayerController? controller) {
    _controller?.removeListener(_listenCallBack);
    _controller = controller;
    _controller?.addListener(_listenCallBack);
    _listenCallBack();
  }

  void _listenCallBack() {
    rebuild();
  }

  Future<bool> rebuild() async {
    if (!mounted) return false;
    if (SchedulerBinding.instance.schedulerPhase != SchedulerPhase.idle) {
      await SchedulerBinding.instance.endOfFrame;
      if (!mounted) return false;
    }
    setState(() {});
    return true;
  }

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (mounted) {
        progressWidth = (currentKey.currentContext?.size?.width ?? 0) - circleWidth;
        if (progressWidth < 0) progressWidth = 0;
      }
    });
    return Visibility(
      visible: _isShowMenu,
      child: Opacity(
          opacity: controller == null ? 0 : 1,
          child: GestureDetector(
            child: Container(
              padding: widget.padding,
              child: widget.isShortStyle ? _buildShort() : _buildNormal(),
            ),
          )),
    );
  }

  Widget _buildShort() {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onHorizontalDragStart: (DragStartDetails details) {
        if (controller?.value.isInitialized != true) {
          return;
        }
        widget.gestureCallback?.call(true);
      },
      onHorizontalDragUpdate: (DragUpdateDetails details) {
        if (controller?.value.isInitialized != true) {
          return;
        }
        seekToRelativePosition(details.globalPosition);
      },
      onHorizontalDragEnd: (DragEndDetails details) async {
        if (controller?.value.isInitialized != true) {
          return;
        }
        try {
          await controller?.seekTo(seekPos!);
        } catch (e) {
          debugLog("seekTo:$e");
        }
        Future.delayed(const Duration(milliseconds: 500), () {
          seekPos = null;
        });
        widget.gestureCallback?.call(false);
      },
      onTapDown: (TapDownDetails details) async {
        if (controller?.value.isInitialized != true) {
          return;
        }
        seekToRelativePosition(details.globalPosition);
        await controller?.seekTo(seekPos!);
        seekPos = null;
        rebuild();
        widget.gestureCallback?.call(false);
      },
      child: Container(
        height: circleWidth + 10,
        margin: const EdgeInsets.only(top: 10),
        key: currentKey,
        child: controller == null
            ? Container()
            : Stack(
                alignment: Alignment.bottomCenter,
                children: [
                  SizedBox(
                    height: 4,
                    child: LinearProgressIndicator(
                      backgroundColor: Colors.white.withOpacity(0.2),
                      valueColor: AlwaysStoppedAnimation(Color(0xffBDBDBD)),
                      value: playDuration,
                    ),
                  ),
                  Positioned(
                    left: _offset,
                    child: Container(
                      width: circleWidth,
                      height: circleWidth,
                      padding: const EdgeInsets.all(0),
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      ),
                    ),
                  ),
                ],
              ),
      ),
    );
  }

  Widget _buildNormal() {
    return Row(
      children: [
        Text(
          timerFormatMMSS(seekPos?.inSeconds ?? controller?.value.position.inSeconds ?? 0),
          style: const TextStyle(color: Colors.white, fontSize: 12),
        ),
        const SizedBox(width: 4),
        Expanded(
          child: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onHorizontalDragStart: (DragStartDetails details) {
              if (controller?.value.isInitialized != true) {
                return;
              }
              widget.gestureCallback?.call(true);
            },
            onHorizontalDragUpdate: (DragUpdateDetails details) {
              if (controller?.value.isInitialized != true) {
                return;
              }
              seekToRelativePosition(details.globalPosition);
            },
            onHorizontalDragEnd: (DragEndDetails details) async {
              if (controller?.value.isInitialized != true) {
                return;
              }
              try {
                await controller?.seekTo(seekPos!);
              } catch (e) {
                debugLog("seekTo:$e");
              }
              Future.delayed(const Duration(milliseconds: 500), () {
                seekPos = null;
              });
              widget.gestureCallback?.call(false);
            },
            onTapDown: (TapDownDetails details) async {
              if (controller?.value.isInitialized != true) {
                return;
              }
              seekToRelativePosition(details.globalPosition);
              await controller?.seekTo(seekPos!);
              seekPos = null;
              rebuild();
              widget.gestureCallback?.call(false);
            },
            child: Container(
              height: circleWidth + 10,
              margin: const EdgeInsets.only(top: 10),
              padding: const EdgeInsets.only(bottom: 10),
              key: currentKey,
              child: controller == null
                  ? Container()
                  : Stack(
                      alignment: Alignment.center,
                      children: [
                        SizedBox(
                          height: 2,
                          child: LinearProgressIndicator(
                            backgroundColor: Colors.white.withOpacity(0.3),
                            valueColor: AlwaysStoppedAnimation(
                              Colors.white,
                            ),
                            value: playDuration,
                          ),
                        ),
                        Positioned(
                          left: _offset,
                          child: Container(
                            width: circleWidth,
                            height: circleWidth,
                            padding: const EdgeInsets.all(0),
                            decoration: BoxDecoration(
                              color: Colors.white,
                              borderRadius: BorderRadius.circular(20),
                            ),
                          ),
                        ),
                      ],
                    ),
            ),
          ),
        ),
        const SizedBox(width: 4),
        Text(
          timerFormatMMSS(controller?.value.duration.inSeconds ?? 0),
          style: const TextStyle(color: Colors.white, fontSize: 12),
        ),
      ],
    );
  }

  @override
  void dispose() {
    _controller?.removeListener(_listenCallBack);
    ShortVideoMenu.removeLister(_menuShowListener);
    super.dispose();
  }
}
